﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace LGTVRemoteForDesktop
{
	public class LGDiscoverer
	{
		private static object lockObj = new object();
		
		public static Hashtable SearchLGTV()
		{
			Hashtable result = new Hashtable();
			
			lock (lockObj)
			{
				var broadcastMessage = Encoding.UTF8.GetBytes("M-SEARCH * HTTP/1.1 \r\n" +
						"HOST: 239.255.255.250:1900\r\n" +
						"MAN: 'ssdp:discover'\r\n" +
						"MX: 3\r\n" +
						"ST: urn:schemas-upnp-org:device:MediaRenderer:1\r\n\r\n");
				var multicastAddress = IPAddress.Parse("239.255.255.250");
				var signal = new ManualResetEvent(false);
				var multicastPort = 1900;

				string LGIP = "";

			
				using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
				{
					EndPoint multicastEp = new IPEndPoint(multicastAddress, multicastPort);
					EndPoint localEp = new IPEndPoint(IPAddress.Any, multicastPort);

					socket.Bind(localEp);
					socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(multicastAddress, IPAddress.Any));

					int tries = 0;
					bool found = false;
					while (!found && tries < 5)
					{
						var response = new byte[512];
						socket.ReceiveFrom(response, ref localEp);
						var responseStr = Encoding.UTF8.GetString(response).TrimEnd('\0');
						Console.WriteLine("[RECV] {0} {1}", localEp.ToString(), responseStr);
						if (responseStr.Contains("LG"))
						{
							LGIP = localEp.ToString().Substring(0, localEp.ToString().IndexOf(':'));

							if (!result.ContainsKey(LGIP))
							{
								string marker = "DLNADeviceName.lge.com: ";

								foreach (string s in responseStr.Replace("\n", "").Split('\r'))
								{
									if (s.StartsWith(marker))
									{
										string deviceName = s.Replace(marker, "");

										result[LGIP] = Uri.UnescapeDataString(deviceName);

										found = true;
									}
								}
							}
						}

						tries++;
					}

					// Sending is not nessesary in most cases.. TV periodically sending packets by itself
					socket.SendTo(broadcastMessage, 0, broadcastMessage.Length, SocketFlags.None, multicastEp);

					socket.Close();
				}
			}

			return result;
		}



	}
}
